import base64
import hashlib
import json
import random
import re
import time

import jwt
import requests
from MySQLdb._exceptions import IntegrityError
from django.conf import settings
from django.contrib.auth.hashers import make_password
from django.core.mail import send_mail
from django.db import transaction
from django.dispatch import receiver
from django.http import JsonResponse
from django.views import View

from carts.views import CartView
from user.models import UserProfile, Address, Weiboprofile
from django.core.cache import caches

from user.tasks import async_send_activation_email, async_send_message
from utils.baseview import BaseView

from utils.sms import SMS
from utils.weiboapi import OauthWeiboApi

# Redis
CODE_CACHE = caches['default']


def users_register(request):
    data = json.loads(request.body)
    print(data)
    uname = data["uname"]
    password = data["password"]
    email = data["email"]
    phone = data["phone"]
    carts=data["carts"]
    verify = data["verify"]
    redis_code = CODE_CACHE.get(f'sms_{phone}')
    print(type(redis_code), type(verify))
    print(f'{redis_code},{verify}')
    if not redis_code:
        return JsonResponse({"code": 400, "error": {"message": "please send the verification code"}})
    if verify != redis_code:
        return JsonResponse({"code": 400, "error": {"message": "verify code is wrong"}})

    if uname == "" or password == "" or email == "" or phone == "":
        return JsonResponse({"code": 400, "message": "please fill in all the information"})
    if UserProfile.objects.filter(username=uname).exists():
        return JsonResponse({"code": 400, "message": "username already exists"})

    # m=hashlib.md5()
    # m.update(password.encode("utf-8"))
    # pwd_md5=m.hexdigest()
    hash_password = make_password(password)
    try:
        # 创建用户
        user = UserProfile.objects.create(username=uname, password=hash_password, email=email, phone=phone)
    except IntegrityError as e:
        # 捕获唯一约束错误
        return JsonResponse({"code": 400, "message": "username already exists"})
    except Exception as e:
        # 其他未知错误
        return JsonResponse({"code": 400, "error": f"register failed, error: {str(e)}"})

    # create token
    token = make_token(uname)
    print(token)

    try:
        # send active email http://127.0.0.1:7000/dadashop/templates/active.html
        async_send_activation_email.delay(email, uname)
    except Exception as e:
        print(f"send_error:{e}")

    #注册购物车合并
    cart_view = CartView()
    offline_cart = data.get('carts')
    carts_count=cart_view.merge_carts(offline_cart,user)
    result = {
        'code': 200,
        'username': uname,
        'data': {'token': token},
        'carts_count': carts_count

    }
    return JsonResponse(result)


def active_view(request):
    code = request.GET.get('code')
    if not code:
        return JsonResponse({"code": 400, "error": "code is required"})
    # 1000_uname
    code = base64.urlsafe_b64decode(code).decode()
    uname = code.split('_')[-1]
    key = f'email_active_{uname}'

    if CODE_CACHE.get(key) == int(code.split('_')[0]):
        try:
            user = UserProfile.objects.get(username=uname, is_active=False)
            user.is_active = True
            user.save()
        except Exception as e:
            return JsonResponse({"code": 400, "error": f"active failed:{e}"})

        return JsonResponse({"code": 200, "data": "激活成功"})
    CODE_CACHE.delete(key)
    return JsonResponse({"code": 400, "error": "active failed"})


def make_token(uname, expire=3600):
    payload = {
        'exp': int(time.time()) + expire,
        'username': uname
    }
    key = settings.JWT_TOKEN_KEY

    return jwt.encode(payload, key, algorithm="HS256")


# def send_activation_email(email, uname):
#     code_num = random.randint(1000, 9999)
#     code = f"{code_num}_{uname}"
#     code = base64.urlsafe_b64encode(code.encode()).decode()
#     active_url = f"http://127.0.0.1:7000/dadashop/templates/active.html?code={code}"
#     message = f"""
#     {uname}
#     <p>Welcome to DadaShop!</p>
#     <p><a href='{active_url}'>Click here to activate your account</a></p>
#     """
#     send_mail(
#         subject='DadaShop Account Activation',
#         message='',
#         from_email=settings.EMAIL_HOST_USER,
#         recipient_list=[email],
#         html_message=message,
#         fail_silently=False
#     )
#     CODE_CACHE.set(f'email_active_{uname}', code_num, timeout=60 * 60 * 24)

def validate_phone_number(phone):
    """
    验证手机号是否规范
    :param phone: 手机号
    :return: 如果手机号规范，返回 True；否则返回 False
    """
    # 中国大陆手机号正则表达式
    pattern = r'^1[3-9]\d{9}$'
    if re.match(pattern, phone):
        return True
    return False


class AddressView(BaseView):
    # @logging_check
    def get(self, request, username):
        user = request.myuser
        print(user)
        try:
            addresses = Address.objects.filter(user_profile=user, is_deleted=False)
            print(addresses)
            address_list = []
            for address in addresses:
                address_list.append({
                    'id': address.id,
                    'receiver': address.receiver,
                    'receiver_mobile': address.receiver_mobile,
                    'address': address.addr,
                    'postcode': address.postcode,
                    'tag': address.tag,
                    'is_default': address.is_default,
                })

            return JsonResponse({'code': 200, 'addresslist': address_list})
        except Exception as e:
            return JsonResponse({'code': 400, 'error': f'get address failed:{e}'})
        pass

    # @logging_check
    def post(self, request, username):
        data = json.loads(request.body)
        print(data)
        receiver = data.get('receiver')
        receiver_mobile = data.get('receiver_phone')
        if not validate_phone_number(receiver_mobile):
            return JsonResponse({'code': 400, 'error': f'phone number is not valid'})
        address = data.get('address')
        postcode = data.get('postcode')
        tag = data.get('tag')
        user = request.myuser
        try:
            is_default = False if Address.objects.filter(user_profile=user, is_deleted=False) else True
            Address.objects.create(user_profile=user,
                                   receiver=receiver, receiver_mobile=receiver_mobile,
                                   addr=address, postcode=postcode,
                                   tag=tag,
                                   is_default=is_default
                                   )

        except Exception as e:
            return JsonResponse({'code': 400, 'error': f'create address failed:{e}'})

        return JsonResponse({"code": 200, "data": f'{username}地址保存成功'})

    # @logging_check
    def delete(self, request, username, address_id):

        id = address_id

        try:
            address = Address.objects.get(id=id, is_deleted=False)
            if address.is_default:
                return JsonResponse({"code": 300, "error": f'{username}不能删除默认地址'})
            address.is_deleted = True
            address.save()
            return JsonResponse({"code": 200, "data": f'{username}地址删除成功'})
        except Exception as e:
            return JsonResponse({'code': 400, 'error': f'delete address failed:{e}'})
        pass

    # @logging_check
    def put(self, request, username, address_id):
        id = address_id
        user = request.myuser
        try:
            addr = Address.objects.get(user_profile=user, id=id, is_deleted=False)
        except Exception as e:
            return JsonResponse({'code': 400, 'error': f'update address failed:{e}'})
        data = json.loads(request.body)
        print(data)
        receiver = data.get("receiver")
        receiver_moblie = data.get("receiver_mobile")
        address = data.get("address")
        tag = data.get("tag")
        try:
            addr.receiver = receiver
            addr.receiver_moblie = receiver_moblie
            addr.addr = address
            addr.tag = tag
            addr.save()  # 保存更新

            return JsonResponse({"code": 200, "data": f'{username}地址更改成功'})
        except Exception as e:
            return JsonResponse({'code': 400, 'error': f'update address failed:{e}'})

        pass


class DefaultAddressView(BaseView):
    # @logging_check
    def post(self, request, username):
        user = request.myuser
        id = json.loads(request.body)['id']
        try:
            newdefault = Address.objects.get(user_profile=user, id=id)
            olddefault = Address.objects.get(user_profile=user, is_default=True, is_deleted=False)
        except Exception as e:
            return JsonResponse({'code': 400, 'error': f'查询地址失败:{e}'})
        try:
            with transaction.atomic():
                olddefault.is_default = False
                olddefault.save()
                newdefault.is_default = True
                newdefault.save()
            return JsonResponse({"code": 200, "data": f'{username}默认地址更改成功'})
        except Exception as e:
            return JsonResponse({'code': 400, 'error': f'修改默认地址失败:{e}'})

    pass


def sendsms_view(request):
    phone = json.loads(request.body)['phone']
    code = random.randint(1000, 9999)
    key = f'sms_{phone}'
    value = str(code)
    print(key, value)

    if not validate_phone_number(phone):
        return JsonResponse({'code': 400, 'error': {"message": f'{phone}手机号不规范'}})
    if CODE_CACHE.get(key):
        print(CODE_CACHE.get(key))
        return JsonResponse(
            {'code': 400, 'error': {"message": f'{phone}短信已发送，请{CODE_CACHE.get(key)}秒后重新发送'}})

    CODE_CACHE.set(key, value, timeout=60 * 5)
    async_send_message.delay(phone, code)
    return JsonResponse({"code": 200, "data": f'{phone}短信已发送'})


class WeiboLoginView(View):
    def get(self, request):
        oauth = OauthWeiboApi(**settings.WEIBO_CONFIG)
        url = oauth.get_auth_url()
        return JsonResponse({"code": 200, "oauth_url": url})


class WeiboAccessView(View):
    def get(self, request):
        # 获取access_token
        code = request.GET.get('code')
        if not code:
            return JsonResponse({"code": 400, "error": "code is not found"})
        url = "https://api.weibo.com/oauth2/access_token"
        access_token_url = OauthWeiboApi(**settings.WEIBO_CONFIG).get_access_token_url(code)
        asscess_html = requests.post(url=url, data=access_token_url).json()
        print(asscess_html)

        # 绑定
        weibo_uid = asscess_html.get('uid')
        weibo_token = asscess_html.get('access_token')
        # 到微博表中查询该uid是否存在 若不存在 则为新用户 需要绑定注册 返回201 存在也不一定绑定注册 若外键为空 返回201 否则直接返回200
        try:
            weibouser = Weiboprofile.objects.get(weibo_uid=weibo_uid)
            if weibouser.user_profile:
                return JsonResponse({'code': '200',
                                     'username': weibouser.user_profile.username,
                                     'token': make_token(weibouser.user_profile.username).decode()
                                     # 签发token 保持登录状态 而不是令牌
                                     })
            else:
                return JsonResponse({"code": 201, "uid": weibo_uid})
        except Exception as e:
            # 若不存在 则为新用户 需要绑定注册 返回201
            print('get weibo error:', e)
            Weiboprofile.objects.create(weibo_uid=weibo_uid, weibo_token=weibo_token)
            return JsonResponse({"code": 201, "uid": weibo_uid})

    # 未绑定需注册
    def post(self, request):
        data = json.loads(request.body)
        if not data:
            return JsonResponse({"code": 400, "error": "data is not found"})
        uid = data.get('uid')
        username = data.get('username')
        password = data.get('password')
        phone = data.get('phone')
        email = data.get('email')

        if UserProfile.objects.filter(username=username).exists():
            return JsonResponse({"code": 400, "error": f'{username}已存在'})
        try:
            weibouser = Weiboprofile.objects.get(weibo_uid=uid)
            if weibouser.user_profile:
                return JsonResponse({"code": 400, "error": f'{uid}已绑定'})
        except Weiboprofile.DoesNotExist:
            # 如果 weibo_uid 不存在，继续执行绑定注册逻辑
            pass

        try:
            with transaction.atomic():
                user = UserProfile.objects.create(username=username, password=make_password(password), phone=phone,
                                                  email=email)
                weibouser = Weiboprofile.objects.get(weibo_uid=uid)
                weibouser.user_profile = user
                weibouser.save()
                user.is_active = True
                user.save()
            # try:
            #     async_send_activation_email.delay(email, username)
            # except Exception as e:
            #     print('send email error:',e)
            return JsonResponse({'code': 200,
                                 'username': user.username,
                                 'token': make_token(user.username)  # 签发token 保持登录状态 而不是令牌
                                 })
        except Exception as e:
            return JsonResponse({'code': 400, 'error': f'register failed:{e}'})

    pass
